package com.gframework.boot.flyway;

import java.util.Collections;
import java.util.List;

import org.springframework.boot.autoconfigure.flyway.FlywayProperties;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.lang.Nullable;

/**
 * flyway执行扩展处理SPI接口，采用spring SPI(spring.factories)接入方式.
 * <p>在使用本框架对flyway进行扩展时，你可以通过配置spring spi本接口子类，来实现对flyway执行操作过程的扩展，
 * 例如设置更多的sql文件路径。
 * <p>本接口的操作会在资源环境加载完后紧接着执行，所以你可以得到一个{@link Environment}接口对象来获取配置。
 * 你也可以通过spring的{@link Binder}类来获取config bean。
 * <p>使用{@link Order}注解可以控制多个flyway spi接口的的执行顺序
 * 
 * <p>
 * {@link #getUrl(String, Environment)}
 * {@link #getUsername(String, Environment)}
 * {@link #getPassword(String, Environment)}
 * 三个方法的配置会一直生效，因此你可以将一个只用来配置连接属性的SPI接口优先执行。
 * 
 * 
 * @since 2.0.0
 * @author Ghwolf
 *
 */
public interface IFlywayExtendSPI {

	/**
	 * flyway执行前的拦截操作.
	 * <p>此方法会提供环境配置信息获取接口对象以及flyway配置信息封装对象，本方法提供给开发人员很大的灵活性，因为你几乎可以修改flyway的任何一个执行参数，但是这通常也是不安全的，
	 * 而且如果错误的修改了部分信息也会造成错误难以排查。
	 * @param flywayProperties flyway配置信息封装类
	 * @param environment 资源配置读取接口
	 */
	default void intercept(FlywayProperties flywayProperties, Environment environment) {}

	/**
	 * 获取数据库连接url，返回null表示不设置，默认会寻找spring.flyway.*的配置.
	 * <p><strong>此配置将会一直生效并未后续的扩展接口提供使用，知道被新的参数覆盖为止</strong>
	 * @param currentUrl 当前url
	 * @param environment 环境配置获取对象
	 */
	@Nullable
	default String getUrl(String currentUrl,Environment environment) {return null ;}
	
	/**
	 * 获取数据库连接用户名，返回null表示不设置，默认会寻找spring.flyway.*的配置.
	 * <p><strong>此配置将会一直生效并未后续的扩展接口提供使用，知道被新的参数覆盖为止</strong>
	 * @param currentUsername 当前用户名
	 * @param environment 环境配置获取对象
	 */
	@Nullable
	default String getUsername(String currentUsername,Environment environment) {return null ;}
	
	/**
	 * 获取数据库连接密码，返回null表示不设置，默认会寻找spring.flyway.*的配置.
	 * <p><strong>此配置将会一直生效并未后续的扩展接口提供使用，知道被新的参数覆盖为止</strong>
	 * @param currentPassword 当前密码
	 * @param environment 环境配置获取对象
	 */
	@Nullable
	default String getPassword(String currentPassword,Environment environment) {return null ;}
	
	/**
	 * 扩展新的sql文件读取路径，例如：classpath:sql/xxx
	 * @param url 数据库连接url，如果没有设置，则未null
	 * @param environment 环境配置获取对象
	 */
	@Nullable
	default List<String> getLocation(@Nullable String url,Environment environment) {return Collections.emptyList();}
	
}
